package com.tencent.user.service.impl;

import com.tencent.basic.constant.VerifyConstants;
import com.tencent.basic.exception.BusinessException;
import com.tencent.basic.service.impl.BaseServiceImpl;
import com.tencent.basic.util.MD5Utils;
import com.tencent.basic.util.StrUtils;
import com.tencent.user.domain.Logininfo;
import com.tencent.user.domain.User;
import com.tencent.user.dto.UserDto;
import com.tencent.user.mapper.LogininfoMapper;
import com.tencent.user.mapper.UserMapper;
import com.tencent.user.service.IUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;

/**
 * 业务实现类：
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LogininfoMapper logininfoMapper;

    /**
     * 发邮件的
     */
    @Autowired
    private JavaMailSender javaMailSender;

    /**
     * 手机号注册
     * @param userDto
     */
    @Override
    public void phoneRegister(UserDto userDto) {
        String phone = userDto.getPhone();
        String phoneCode = userDto.getPhoneCode();
        String password = userDto.getPassword();
        String passwordRepeat = userDto.getPasswordRepeat();
        // 1. 校验空值
        if (StringUtils.isEmpty(phone.trim())
                || StringUtils.isEmpty(phoneCode)
                || StringUtils.isEmpty(password)
                || StringUtils.isEmpty(passwordRepeat)) {
            throw new BusinessException("请输入正确的数据");
        }


        // 2. 校验密码是否相同
        if (!password.equals(passwordRepeat)) {
            throw new BusinessException("两次密码不一致");
        }
        // 3. 校验手机验证码是否过期
        Object redisPhoneCode = redisTemplate.opsForValue().get(VerifyConstants.REGISTER_PREFIX + phone);
        if (redisPhoneCode == null) {
            throw new BusinessException("手机验证码已过期");
        }
        // 4. 校验手机验证码是否正确
        if (!phoneCode.equalsIgnoreCase(redisPhoneCode.toString().split(":")[0])) {
            throw new BusinessException("手机验证码错误");
        }

        // 5. 添加logininfo信息 - 因可以获取自增长id 添加到user中去 所以先添加logininfo
        // 6. 添加user信息
        User user = userDto2User(userDto);

        Logininfo logininfo = user2Logininfo(user);

        // 保存logininfo的信息
        logininfoMapper.save(logininfo);

        // 获取logininfo的ID 并在user里设置logininfo的ID
        user.setLogininfoId(logininfo.getId());
        // 保存到数据库
        userMapper.save(user);
    }

    /**
     * 邮箱注册
     * @param userDto
     */
    @Override
    public void emailRegister(UserDto userDto) {
        String email = userDto.getEmail();
        String password = userDto.getPassword();
        String passwordRepeat = userDto.getPasswordRepeat();
        // 1. 校验空值
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordRepeat)) {
            throw new BusinessException("请正确填写！");
        }
        // 2. 校验邮箱是否已经注册过
        User eUser = userMapper.loadByEmail(email);
        if (eUser != null) {
            throw new BusinessException("邮箱已注册，请勿重复注册！");
        }
        // 3. 校验密码是否一致
        if (!password.equals(passwordRepeat)) {
            throw new BusinessException("两次密码不一致");
        }
        // 4. 将信息添加到logininfo
        User user = userDto2User(userDto);
        Logininfo logininfo = user2Logininfo(user);
        logininfo.setDisable(false);
        logininfoMapper.save(logininfo);

        user.setLogininfoId(logininfo.getId());
        userMapper.save(user);

        // 5. 创建复杂邮件对象
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        // 6. 发送复杂邮件的工具类
        try {
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true,"utf-8");
            helper.setFrom("1004370140@qq.com");
            helper.setSubject("账户激活邮件");
            helper.setText("<h1>你的账户已注册!</h1>" +
            "<a href='http://localhost:8080/user/active/"+user.getId()+"'>点击该链接激活</a>",true);
            //添加附件
            helper.addAttachment("R-C.jpeg",new File("C:\\Users\\ghostvv\\Desktop\\R-C.jpeg"));
            //收件人
            helper.setTo(userDto.getEmail());
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        // 7. 发送邮件
        javaMailSender.send(mimeMessage);

    }

    /**
     * 激活账号
     * @param id
     */
    @Override
    public void userActive(Long id) {
        User user = userMapper.loadById(id);
        Logininfo logininfo = logininfoMapper.loadById(user.getLogininfoId());
        logininfo.setDisable(true);
        logininfoMapper.update(logininfo);
    }

    /**
     * 从userDto对象转到User
     * @param userDto
     * @return
     */
    private User userDto2User(UserDto userDto) {
        User user = new User();
        // 设置user的信息 -  有手机号 就是手机号注册(手机的数据模型没有email 不同担心绑定的问题) 有邮箱 就是邮箱注册
        if (userDto.getPhone() == null) {
            user.setUsername(userDto.getEmail());
            user.setEmail(userDto.getEmail());

        } else {
            user.setUsername(userDto.getPhone());
            user.setPhone(userDto.getPhone());
        }

        // 加密加盐
        String salt = StrUtils.getComplexRandomString(32);
        String md5Password = MD5Utils.encrypByMd5(userDto.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Password);

        return user;
    }

    /**
     * 从User对象转到Logininfo
     * @param user
     * @return
     */
    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();

        // BeanUtils拷贝属性(字段对应)方法
        BeanUtils.copyProperties(user, logininfo);
        // 设置为用户
        logininfo.setType(1);

        return logininfo;
    }

    /**
     * 重写添加方法 在操作t_employee或t_user操作的时候都要同步操作t_logininfo
     * @param user
     */
    @Override
    public void save(User user) {
        // 分析 传递过来的user对象 应该是什么都有了 但是密码是明文 没有盐值
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = MD5Utils.encrypByMd5(user.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        // 添加到logininfo中
        Logininfo logininfo = user2Logininfo(user);
        logininfoMapper.save(logininfo);
        // 获取logininfo的ID 并在user里设置logininfo的ID
        user.setLogininfoId(logininfo.getId());
        // 保存到数据库
        super.save(user);
    }

    /**
     * 重写添加方法 在操作t_employee或t_user操作的时候都要同步操作t_logininfo
     * @param id
     */
    @Override
    public void remove(Long id) {
        // 通过id查找user 通过user查找 登录信息id 再通过id删除登录信息 再删除自己
        User user = userMapper.loadById(id);
        logininfoMapper.remove(user.getLogininfoId());
        super.remove(id);
    }

    /**
     * 重写添加方法 在操作t_employee或t_user操作的时候都要同步操作t_logininfo
     * @param user
     */
    @Override
    public void update(User user) {
        // 不知道修改什么 我们就先加盐加密咯
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = MD5Utils.encrypByMd5(user.getPassword()+salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);

        // logininfo_id不能修改 ∴获取登录信息id
        // 修改的时候 会传递id 根据id查出user对象 再查登录id
        Long logininfo_id = userMapper.loadById(user.getId()).getLogininfoId();

        // logininfo的type不修改 是用户就是用户 copy对象字段值
        Logininfo logininfo = user2Logininfo(user);
        // 把id给他 才能去修改
        logininfo.setId(logininfo_id);

        logininfoMapper.update(logininfo);
        super.update(user);
    }
}
